<?php
//幂等消费类
namespace App\Services\Tools;

use App\Enums\IdempotentJobName;
use App\Enums\RedisKeyEnum;
use Illuminate\Support\Facades\Log;
class IdempotentConsume
{
    /**
     * 添加幂等的redisKey
     * @param $jobName
     * @param $uniKey
     * author Hso
     */
    public function checkIdempotentRedisKey($jobName,$uniKey){
        if(empty($uniKey)){
            return true;
        }
        $redisKey = RedisKeyEnum::IdempotentRedisKey.$jobName;
        $redis = app('redis');
        $isMem = $redis->zAdd($redisKey,time(),$uniKey);
        $redis->expire($redisKey, 3600*24);    //设置24个小时的过期时间，如果1小时内无队列投递自动消失如果有，定时去删除有序集合中超过10min的键
        if(!$isMem){
            Log::error("{$jobName}:uk:{$uniKey}已消费");
            return false;
        }else{
            return true;
        }
    }
    //失败之后删除幂等消费锁
    public function deleteIdempotentRedisKey($jobName,$uniKey){
        if(empty($uniKey)){
            return true;
        }
        $redisKey = RedisKeyEnum::IdempotentRedisKey.$jobName;
        $redis = app('redis');
        $uniKey = is_array($uniKey)?$uniKey:[$uniKey];
        $res = $redis->zRem($redisKey,...$uniKey);
        $uniKey = json_encode($uniKey);
        Log::error("{$jobName}:uk:{$uniKey}执行失败");
        return $res;
    }
    
    //定期删除对应幂等消费job的zset（暂定时间为10min）
    public function cronDeleteOutTimeKey(){
        $keys = RedisKeyEnum::IdempotentRedisKey;
        $redis = app('redis');
        $jobNames = IdempotentJobName::ALL_JOB_NAME;
        $time = time()-60*60*24;
        foreach ($jobNames as $key){
            $key = $keys.$key;
            if($redis->exists($key)){
                $ttlKey = $redis->zRangeByScore($key, 0, $time);
                if($ttlKey){
                    $redis->zRem($key,...$ttlKey);
                }
            }
        }
    }
    
    //投递easySwoole项目投递gift_main job，消费时清除该key
    public function removeEasySwooleGiftJob($jobName,$giftIds=[]){
        $redisKey = RedisKeyEnum::EasySwooleQueueSuccessKey;
        $queueKey = $this->jobNameToQueueRedisKey($jobName);
        if(!$queueKey){
            return false;
        }
        $remKey = json_encode(
            ['queue' => $queueKey, 'data' => $giftIds]
        );
//        $redis = new \redis();
        $redis = app('redis');
        return $redis->zRem($redisKey,$remKey);
    }
    
    private function jobNameToQueueRedisKey($jobName){
        $job2QueueKey = [
            'GiftJob' => 'gift_queue'
        ];
        return isset($job2QueueKey[$jobName])?$job2QueueKey[$jobName]:'';
    }
}
